﻿using B.S.BasicData.Api.Read.Application.Command.Account;
using B.S.BasicData.Api.Read.DTOs;
using B.S.BasicData.Api.Read.Extensions;
using B.S.BasicData.Domain.Entities;
using B.S.BasicData.ErrorCode;
using B.S.BasicData.Infrastructure.Interface;
using MD5Hash;
using MediatR;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace B.S.BasicData.Api.Read.Application.Handler.Account
{
    /// <summary>
    /// 中介者模式  -  登录(账号)处理类
    /// </summary>
    public class LoginAccountHandler : IRequestHandler<LoginAccountCommand, ApiResult<AccountDTO>>
    {
        private readonly IBaseRepository<AccountModel> accountRepo;
        private readonly IBaseRepository<RoleModel> roleRepo;
        private readonly IBaseRepository<AccountRoleModel> accountRoleRepo;
        /// <summary>
        /// 注入仓储
        /// </summary>
        /// <param name="accountRepo">账号仓储</param>
        /// <param name="roleRepo">角色仓储</param>
        /// <param name="accountRoleRepo">账号角色仓储</param>
        public LoginAccountHandler(IBaseRepository<AccountModel> accountRepo,IBaseRepository<RoleModel> roleRepo,IBaseRepository<AccountRoleModel> accountRoleRepo)
        {
            this.accountRepo = accountRepo;
            this.roleRepo = roleRepo;
            this.accountRoleRepo = accountRoleRepo;
        }

        public async Task<ApiResult<AccountDTO>> Handle(LoginAccountCommand request, CancellationToken cancellationToken)
        {
            ApiResult<AccountDTO> res = new ApiResult<AccountDTO>(); //实例化响应包装类
            //使用requst.AccountName 查找 账号对象
            var account = accountRepo.GetAll().Where(x => x.AccountName == request.AccountName).FirstOrDefault();
            if (account == null)
            { //没有找到账号,直接返回失败的响应包装类对象
                res.Code = ApiEnum.Failed;
                res.Msg = "账号不存在!";
                return res;//不存在,要直接返回
            }

            var pwd = request.Pwd.GetMD5WithSalt(account.Salt);//加了盐
            if (pwd != account.Pwd) {//比较密码是否相等
                res.Code = ApiEnum.Failed;
                res.Msg = "密码不正确!";
                return res;
            }

            //登录成功,给账号查找角色
            var accRole = accountRoleRepo.GetAll().Where(x=>x.AccountId==account.Id).FirstOrDefault();//根据账号id,查找账号角色关系
            if (accRole == null) {
                res.Code = ApiEnum.Failed;
                res.Msg = "请联系管理员给账号配置角色!";
                return res;
            }

            var role =await roleRepo.GetModel(accRole.RoleId);
            if (role == null) {
                res.Code = ApiEnum.Failed;
                res.Msg = "请联系管理员配置角色!";
                return res;
            }

            var refreshToken = this.CreateFreshToken();
            //实例化账号DTO
            var accountDto = new AccountDTO()
            {
                AccountName = account.AccountName,
                RoleName = role.RoleName,
                RealName = account.RealName,
                JwtToken = this.CreateTokenString(account.AccountName, role.RoleName, account.RealName),
                RefreshToken = refreshToken //颁发刷新token
            };

            account.RefreshToken = refreshToken; //给用户保存刷新token
            account.RefreshTokenTime = DateTime.Now; //新的刷新token创建的时间
            account.FingerPoint = request.FingerPoint; //录入刷新token的指纹

            //把账号信息保存到数据库
            await accountRepo.UpdateAsync(account);

            res.Code = ApiEnum.Success;
            res.Msg = "恭喜您,登陆成功!";
            res.Data = accountDto;

            return res;


        }

         


    }
}
